package com.essence.grabiec104.grab.strategy;

import com.essence.common.task.IntervalTask;
import com.essence.common.task.TaskLauncher;
import com.essence.grabiec104.grab.model.AlarmRule;
import com.essence.grabiec104.grab.router.Publisher;
import com.essence.grabiec104.grab.service.AlarmService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;

import javax.annotation.PostConstruct;
import java.util.List;

@Component
@Slf4j
public class StrategyDispatcher {
    public static final TaskLauncher LAUNCHER = new TaskLauncher(1);

    public enum ZCtxParam  {
        INSTANCE;

        private final ZContext publishCtx;
        private final String inprocName;

        ZCtxParam() {
            this.publishCtx = new ZContext(1);
            this.inprocName = "inproc://dispatcher_worker";
        }

        public ZContext getPublishCtx() {
            return publishCtx;
        }

        public String getInprocName() {
            return inprocName;
        }
    }
    @Autowired
    private ControlFrameTotalStrategy controlFrameTotalStrategy;
    @Autowired
    private ControlPointTotalStrategy controlPointTotalStrategy;
    @Autowired
    private SameYkPointStrategy sameYkPointStrategy;
    @Autowired
    private SameSdPointStrategy sameSdPointStrategy;
    @Autowired
    private YtPrecisionStrategy ytPrecisionStrategy;
    @Autowired
    private YcSlopeStrategy ycSlopeStrategy;

    @Autowired
    private AlarmService alarmService;

    private final ThreadLocal<ZMQ.Socket> workerPairThreadLocal = new ThreadLocal<>();

    @PostConstruct
    public void doTask() {
        // 创建责任链
        controlFrameTotalStrategy.setNext(controlPointTotalStrategy);
        controlPointTotalStrategy.setNext(sameYkPointStrategy);
        sameYkPointStrategy.setNext(sameSdPointStrategy);
        sameSdPointStrategy.setNext(ytPrecisionStrategy);
        ytPrecisionStrategy.setNext(ycSlopeStrategy);

        // 创建任务
        LAUNCHER.addTask(new IntervalTask("StrategyOperator", 5, 5) {
            @Override
            public void execute(String taskName, TaskLauncher launcher) throws Exception {
                ZMQ.Socket workPair = workerPairThreadLocal.get();
                if (workPair == null) {
                    workPair = Publisher.ZCtxParam.INSTANCE.getPublishCtx().createSocket(SocketType.PUSH);
                    workPair.connect(Publisher.ZCtxParam.INSTANCE.getInprocName());
                    workerPairThreadLocal.set(workPair);
                }
                controlFrameTotalStrategy.setWorkerSocket(workPair);

                // 执行策略链
                List<AlarmRule> rules = alarmService.getAllAlarmRule();
                controlFrameTotalStrategy.strategyOperate(rules);
            }

            @Override
            public void notifyFailure(String taskName, int consecutiveFailures, TaskLauncher launcher, Exception ex) {
                log.error("StrategyOperator notifyFailure", ex);
            }
        });
    }
}
